import type { ConversationsProps } from 'ant-design-x-vue'
import type { FullModelInfo } from '@/services/model/type'
import type { ConversationInfo } from '@/services/chat/type'
import { h, ref, computed, readonly, createVNode } from 'vue'
import { ExclamationCircleOutlined, MessageOutlined, ToTopOutlined } from '@ant-design/icons-vue'
import { Modal } from 'ant-design-vue'
import { defineStore } from 'pinia'
import dayjs from 'dayjs'
import { t } from '@/i18n'
import xModelService from '@/services/model'
import xChatService from '@/services/chat'
import xChatAgentService from '@/services/chat/x-agent'
import router from '@/router'
import { geneGUID } from '@/utils/generate'
import { useGlobalStore } from '@/stores/global'

// 全局存储
const globalStore = useGlobalStore()

/**
 * 聊天会话管理
 *
 * @description 管理会话聊天记录与实时聊天交互功能
 */
export const useChatStore = defineStore('chat', () => {
  // 会话历史
  const convsHistory = ref<ConversationInfo[]>([])
  // 激活的会话ID
  const activeConvId = ref<string>('')
  // 是否正在响应中
  const isSystemTyping = ref<boolean>(false)
  // 锁定的会话ID
  const lockConvId = ref<string>('')

  // ----- Functions -----

  /**
   * 格式化时间字符串
   *
   * @param timestamp 千分位时间戳
   * @returns
   */
  const formatRelativeTime = (timestamp: number): string => {
    const targetDate = dayjs(timestamp)
    const now = dayjs()

    // 判断是否是今天
    if (targetDate.isSame(now, 'day')) {
      return t('system.timeGroup.today')
    }

    // 判断是否是本周（自然周，dayjs默认周开始是周日）
    if (targetDate.isSame(now, 'week')) {
      return t('system.timeGroup.thisWeek')
    }

    // 判断是否是本月
    if (targetDate.isSame(now, 'month')) {
      return t('system.timeGroup.thisMonth')
    }

    // 其他情况返回更早
    return t('system.timeGroup.earlier')
  }

  // ----- Getters -----

  const readConvsHistory = computed<ConversationsProps['items']>(() => {
    return convsHistory.value.map((item) => ({
      key: item.id as string,
      title: item.title,
      label: h(
        'div',
        {
          style: {
            display: 'flex',
          },
        },
        [
          h(item.isTop ? ToTopOutlined : MessageOutlined, {
            style: { margin: '0 5px 0 0' },
          }),
          h(
            'div',
            {
              style: {
                overflow: 'hidden',
                'text-overflow': 'ellipsis',
                'white-space': 'nowrap',
              },
            },
            item.title,
          ),
        ],
      ),
      group: item.isTop ? t('chat.conversation.pinGroup') : formatRelativeTime(item.timestamp),
      isTop: !!item.isTop,
      timestamp: item.timestamp,
    }))
  })

  const readActiveConvTitle = computed(() => {
    const activeConv = convsHistory.value.find((item) => item.id === activeConvId.value)
    return activeConv ? activeConv.title : t('chat.newConversation')
  })

  // ----- Actions -----

  /**
   * 初始化聊天数据
   */
  const initChatStore = async () => {
    //  加载聊天历史
    convsHistory.value = await xChatService.getInstance().getConvsHistory()
    // 读取浏览器path中的id
    const guid = router.currentRoute.value.params.guid
    // 初始化
    if (Array.isArray(guid)) {
      changeActiveConvId(guid[0])
    } else {
      changeActiveConvId('')
    }
  }

  /**
   * 切换激活的会话ID
   *
   * @param convId 会话ID
   */
  const changeActiveConvId = async (convId: string) => {
    if (convId === activeConvId.value) {
      return
    }
    const run = async () => {
      activeConvId.value = convId
      router.replace({
        name: 'Chat',
        params: {
          guid: convId,
        },
      })
      // 加载新会话
      await xChatAgentService.getInstance().load(convId)
    }
    if (lockConvId.value && lockConvId.value !== convId) {
      // 已锁定
      Modal.confirm({
        title: t('chat.abort.confirmTitle'),
        icon: createVNode(ExclamationCircleOutlined),
        content: t('chat.abort.confirmContent'),
        onOk: async () => {
          await abort()
          await run()
        },
      })
    } else {
      await run()
    }
  }

  /**
   * 生成指定会话标题
   *
   * @param convId 会话ID
   * @param model 模型数据
   */
  const geneConvTitle = async (convId: string, model: FullModelInfo) => {
    // 生成标题
    const messages = await xChatService.getInstance().getConvChatsHistory(convId)
    const provider = await xModelService.getInstance().getProviderInstance(model.supplier.id)
    const title = await provider.geneTitle(model.key, messages)
    if (title) {
      // 修改会话
      await setConvInfo(convId, { title })
    }
  }

  /**
   * 修改一条会话信息
   *
   * @param convId 会话ID
   * @param data.title 标题（可选）
   * @param data.isTop 是否置顶（可选）
   */
  const setConvInfo = async (convId: string, data: { title?: string; isTop?: boolean }) => {
    await xChatService.getInstance().setConvInfo(convId, data)
    //  刷新聊天历史
    convsHistory.value = await xChatService.getInstance().getConvsHistory()
  }

  /**
   * 删除一条会话信息（包括聊天信息）
   *
   * @param convId 会话ID
   * @param title 标题
   */
  const delConvInfo = async (convId: string) => {
    await xChatService.getInstance().delConvInfo(convId)
    //  刷新聊天历史
    convsHistory.value = await xChatService.getInstance().getConvsHistory()
    if (convId === activeConvId.value) {
      // 如果是当前会话，则清空
      await changeActiveConvId('')
    }
  }

  /**
   * 清空全部会话信息
   */
  const clearConvs = async () => {
    await xChatService.getInstance().clearAllConvs()
    //  刷新聊天历史
    convsHistory.value = await xChatService.getInstance().getConvsHistory()
    await changeActiveConvId('')
  }

  /**
   * 发送一条消息
   *
   * @param modelId 模型ID
   * @param content 消息内容
   */
  const send = async (modelId: string, content: string) => {
    isSystemTyping.value = true
    try {
      if (!content) {
        throw new Error(t('chat.input.emptyInputTip'))
      }
      if (!modelId) {
        throw new Error(t('model.selectModelTip'))
      }
      if (!activeConvId.value) {
        // 创建新聊天
        const convId = geneGUID()
        // 标记锁定
        lockConvId.value = convId
        await changeActiveConvId(convId)
      } else {
        // 标记锁定
        lockConvId.value = activeConvId.value
      }
      const attachs = globalStore.getCurrentAttachs()
      // 清空附件
      globalStore.clearCurrentAttachs()
      // 发送消息
      await xChatAgentService
        .getInstance()
        .send(activeConvId.value, modelId, content, attachs, async () => {
          //  刷新聊天历史
          convsHistory.value = await xChatService.getInstance().getConvsHistory()
        })
    } catch (error) {
      window.console.error(error)
      throw error
    } finally {
      lockConvId.value = ''
      isSystemTyping.value = false
      // 重载当前会话
      await xChatAgentService.getInstance().load(activeConvId.value)
    }
  }

  /**
   * 打断输入中消息
   */
  const abort = async () => {
    lockConvId.value = ''
    isSystemTyping.value = false
    await xChatAgentService.getInstance().abort()
  }

  return {
    /** getter: 当前会话历史记录（已排序） */
    readConvsHistory,
    /** getter: 当前激活的会话ID */
    readActiveConvKey: readonly(activeConvId),
    /** getter: 当前激活的会话标题 */
    readActiveConvTitle,
    /** getter: 聊天泡泡属性 */
    readChatBubbleRoles: xChatAgentService.getInstance().chatBubbleRoles,
    /** getter: 聊天泡泡数据 */
    readConvsBubbleItems: xChatAgentService.getInstance().chatBubbleItems,
    /** getter: 是否系统正在响应 */
    isSystemTyping: readonly(isSystemTyping),
    /** action: 初始化聊天数据 */
    initChatStore,
    /** action: 切花激活的会话ID */
    changeActiveConvId,
    /** action: 生成指定会话标题 */
    geneConvTitle,
    /** action: 修改一条会话标题 */
    setConvInfo,
    /** action: 删除一条会话信息（包括聊天信息）*/
    delConvInfo,
    /** action: 清空全部会话信息 */
    clearConvs,
    /** action: 发送一条消息 */
    send,
    /** action: 打断输入中消息 */
    abort,
  }
})
